ReferencePipeline
用于描述中间管道阶段或者管道源阶段的抽象基类。
继承 AbstractPipeline,实现 Stream
AbstractPipeline
继承 PipelineHelper,实现 BaseStream
文档说明
- 管道类的抽象父类,是 Stream 接口及其原生特化的核心实现。它会管理流管道的构建及评估
- AbstractPipeline 代表一个流管道的的初始部分,它封装了流的源,以及一个或多个中间操作
- 每个 AbstractPipeline 对象通常被称为 stage(阶段),每个阶段描述的,要么是流的源,要么是一个中间操作
- 每个 AbstractPipeline 对象通常被称为 stage(阶段),每个阶段描述的,要么是流的源,要么是一个中间操作
- 一个具体的中间阶段通常通过一个 AbstractPipeline 构建,一个 “类型特化(shape-specific)管道” 继承它(如:IntPipeline)后仍旧抽象,再由一个“操作特化(operation-specific)”的具体类去继承前者
- AbstractPipeline 包含了大多数评价管道的机制,并且实现方法,这些实现的方法都会被操作使用到;“类型特化”的类会添加一些辅助方法,用于将结果集装到合适的“类型特化”的容器当中(也就是避免装箱拆箱的操作)
- 在链接一个新的中间操作,或者执行一个终止操作后,这个流就会被标记为已消费,并且不会再有更多的中间或终止操作添加到这个流实例当中
- implNote
- 对于串行流,以及所有中间操作都无状态的的并行流两种情况,管道的计算是在单个的过程中完成的,所谓的单个的过程就是,将所有的操作都放到一起完成
- 对于有状态操作的并行流,执行会被分为多个“段”,当中每个有状态的操作都会在段的结尾打上标识,然后每个段都会单独地进行计算,并且每段的输出结果都会作为下一段的输入
- 在所有的情况中,在一个终止操作开始之前,源数据都不会被消费
属性
- previousStage
- 上游的 pipeline,源阶段置 null
- 上游的 pipeline,源阶段置 null
- sourceStage
- 指向管道头的反指向链,源阶段为自身
- 指向管道头的反指向链,源阶段为自身
- sourceOrOpFlags
- combinedFlags
- depth
- 当前管道对象与流的源(串行)或前状态(并行)之间,中间操作的个数
- 在管道准备进行计算的时间点有效
- 当前管道对象与流的源(串行)或前状态(并行)之间,中间操作的个数
- parallel
- 是否并行,只在流的源阶段有效
- 是否并行,只在流的源阶段有效
- sourceSpliterator
- 源的 spliteraror,只在管道头有效
- 在管道被消费前,若为“非空”,则 sourceSupplier 必须为 null
- 在管道被消费后,若为“非空”,则将其置 null
- 源的 spliteraror,只在管道头有效
- sourceSupplier
- 源的 supplier,只在管道头有效
- 在管道被消费前,若为“非空”,则 sourceSpliterator 必须为 null
- 在管道被消费后,若为“非空”,则将其置 null
- 源的 supplier,只在管道头有效
构造方法
构造方法一:构造流管道的头
上游 pipeline 置 null,将带有数据源引用的 spliterator 赋给当前 pipeline,
将当前阶段标记为源阶段,配置操作属性,当前深度初始化为0,设置 串行/并行 标记
AbstractPipeline(Supplier<? extends Spliterator<?>> source, int sourceFlags, boolean parallel) { this.previousStage = null; this.sourceSupplier = source; this.sourceStage = this; this.sourceOrOpFlags = sourceFlags & StreamOpFlag.STREAM_MASK; // The following is an optimization of: // StreamOpFlag.combineOpFlags(sourceOrOpFlags, StreamOpFlag.INITIAL_OPS_VALUE); this.combinedFlags = (~(sourceOrOpFlags << 1)) & StreamOpFlag.INITIAL_OPS_VALUE; this.depth = 0; this.parallel = parallel; }
构造方法二:构造用于追加一个中间操作到一个既有的 pipeline 上
断言,若传入的上游 pipeline 已被链接过消费,则抛出异常;
将上游 pipeline 标记为已消费;将上游 pipeline 的下游指向当前 pipeline;将当前 pipeline 的上游指向上游 pipeline;
配置操作属性;深度 +1
AbstractPipeline(Spliterator<?> source, int sourceFlags, boolean parallel) { this.previousStage = null; this.sourceSpliterator = source; this.sourceStage = this; this.sourceOrOpFlags = sourceFlags & StreamOpFlag.STREAM_MASK; // The following is an optimization of: // StreamOpFlag.combineOpFlags(sourceOrOpFlags, StreamOpFlag.INITIAL_OPS_VALUE); this.combinedFlags = (~(sourceOrOpFlags << 1)) & StreamOpFlag.INITIAL_OPS_VALUE; this.depth = 0; this.parallel = parallel; }
抽象方法
abstract Sink<E_IN> opWrapSink(int flags, Sink<E_OUT> sink)
说明文档
- 接收一个接收操作结果的 Sink,并返回一个接收当前操作的输入类型的元素并执行操作的 Sink,将结果传递到提供的 Sink 中
- apiNote
- 实现类可能使用 flag 参数去优化 sink 的包装
- 例如,如果输入已经是 DISTINCT ,那么 distinct() 方法的实现只需要返回 sink
实现方法
wrapAndCopyInto
@Override final <P_IN, S extends Sink<E_OUT>> S wrapAndCopyInto(S sink, Spliterator<P_IN> spliterator) { copyInto(wrapSink(Objects.requireNonNull(sink)), spliterator); return sink; }
- 通过 wrapSink 方法获取最初的 sink
- 通过 copyInto 方法遍历元素
- 循例将执行到的 sink 返回,即使没什么意义
wrapSink
@Override @SuppressWarnings("unchecked") final <P_IN> Sink<P_IN> wrapSink(Sink<E_OUT> sink) { Objects.requireNonNull(sink); for ( @SuppressWarnings("rawtypes") AbstractPipeline p=AbstractPipeline.this; p.depth > 0; p=p.previousStage) { sink = p.opWrapSink(p.previousStage.combinedFlags, sink); } return (Sink<P_IN>) sink; }
- 传入下一阶段的 sink,获取当前阶段的 sink,循环获取最初阶段的 sink
copyInto
@Override final <P_IN> void copyInto(Sink<P_IN> wrappedSink, Spliterator<P_IN> spliterator) { Objects.requireNonNull(wrappedSink); if (!StreamOpFlag.SHORT_CIRCUIT.isKnown(getStreamAndOpFlags())) { wrappedSink.begin(spliterator.getExactSizeIfKnown()); spliterator.forEachRemaining(wrappedSink); wrappedSink.end(); } else { copyIntoWithCancel(wrappedSink, spliterator); } }
- 判断是否有短路操作(filter 之类的中间操作)
- 遵循 Sink 中定义的操作顺序调用遍历方法,最终调用数据源的 tryAdvance方法
ReferencePipeline.Head
表示 ReferencePipeline 的源阶段
继承了 ReferencePipeline(二者在大部分属性的设定上是类似的,但存在一些属性是不同的,比如说 Head 的 previousStage 是空的,而 ReferencePipeline 则存在 previousStage,等等)
构造方法
本质上是调用的是 AbstractPipeline 的构造方法一,
ReferencePipeline(Supplier<? extends Spliterator<?>> source, int sourceFlags, boolean parallel) { super(source, sourceFlags, parallel); }
ReferencePipeline(Spliterator<?> source, int sourceFlags, boolean parallel) { super(source, sourceFlags, parallel); }
ReferencePipeline.StatelessOp
一个基类,针对一个流的无状态的中间阶段,同样集成了 ReferencePipeline
构造方法
本质上调用的是 AbstractPipeline 的构造方法二
StatelessOp(AbstractPipeline<?, E_IN, ?> upstream, int opFlags) { super(upstream, opFlags); assert upstream.getOutputShape() == inputShape; }